八. 使用vue+antd搭建后台管理系统(实现篇)

您所在的位置:网站首页 ant design vue 学习 八. 使用vue+antd搭建后台管理系统(实现篇)

八. 使用vue+antd搭建后台管理系统(实现篇)

2024-01-19 10:06| 来源: 网络整理| 查看: 265

写在前面

上一篇完成了后台管理系统的基础搭建和一些具体功能,现在就直接开始完成页面功能的具体实现和项目优化。

页面基础功能实现 1.登录页

分为 用户名+密码登录 和 手机号+验证码登录两种,验证码mock随机六位数返回,登录成功会返回一个token,请求接口时携带token,图片是从千图网上扣的(白嫖一波)。

2.layout布局

layout 布局按照之前设想的那样,左边导航菜单,上面面包屑+用户信息,再往下就是标签页。

导航栏 看了vue-element-admin 的代码,发现还可以导航栏递归生成,顿时眼前一亮,然后照着写了一遍,发现有很多地方可能用不到,比如外链,再比如 alwaysShow 等,就简化了下,逻辑更加简单。

以前还写过用 v-for 和 v-if(item.children)  然后再 v-for item.children 再 v-if这种方式去写,然后改的时候头皮发麻

标签页 模块主要的难点是(自己手写的,没用tab组件):

1.标签页数量超出可显示区域后显示 左右移动按钮,点击移动按钮移动标签页;

2.点击新页面的时候,当前位置挪动到最后面,显示当前页面的标签页

然后再添加上下布局,得更改下样式和布局方式即可。

3.权限验证

由于之前做过的系统都是后端传路由过来,所以这是第一次尝试使用前端自己控制路由,不过还好vue-element-admin 里面权限控制已经做得非常完美了;画了个流程图,看看就好...

4.echarts图

这里添加了各种的图大部分常用的各种形态,echarts图,柱状图、折线图、饼图、关系图、地图、词云图等。如地图:分布图、散点图、航线图、热力图等,均可实现 点击下钻

如果你要做词云图或者水球图,得先去安装对应插件,如词云图需要安装 echarts-wordcloud

5.系统管理

这个按照之前设想的那样,做一个用户管理和一个角色管理,系统管理只有管理员权限才能看到,可以修改用户所看的菜单,以一个树形结构的方式展示, 但是mock不是很好模拟这些数据,所以就只做了一个假的。

6.其他

之后还添加一些我觉得比较有意思的组件,如:头像上传裁剪 、webSocket、上传Excel等有兴趣可以看看。

优化

虽然页面已经写完了,但是发现还是存在很多问题,如首页加载时间太长,打包文件太大等问题,然后就开始进一轮优化。

1. 关闭生产环境 sourceMap

关闭方法:vue.config.js 设置 productionSourceMap  为 false 即可

productionSourceMap: false, 2. 关闭预加载和预编译

vue会预加载后面的路由导致首屏加载时间较长,所以这里去掉。

关闭方法:vue.config.js 设置 chainWebpack :  

config.plugins.delete('prefetch'); config.plugins.delete('preload'); 3. g-zip压缩

使用 compression-webpack-plugin  插件 进行g-zip压缩,需要nginx配合

const CompressionWebpackPlugin = require('compression-webpack-plugin'); config.plugin('CompressionWebpackPlugin').use(CompressionWebpackPlugin, [{ filename: '[path].gz[query]', algorithm: 'gzip', test: /\.js$|\.css/, //匹配文件名 threshold: 10240, //对超过10k的数据压缩 minRatio: 0.8 } ]); 4. 清除生产环境console 和debugger

vu-cli4里面默认使用的是 terser,我们只需修改这个的属性即可。

config.optimization.minimizer('terser').tap(args => { args[0].terserOptions.compress.warnings = false; args[0].terserOptions.compress.drop_console = true args[0].terserOptions.compress.drop_debugger = true; args[0].terserOptions.compress.pure_funcs = ['console.*']; return args; }); 5. splitChunks 优化 const isProd = process.env.NODE_ENV === 'production'; config.when(isProd, config => { config.optimization.splitChunks({ chunks: 'all', cacheGroups: { libs: { name: 'chunk-libs', test: /[\\/]node_modules[\\/]/, priority: 10, chunks: 'initial' }, commons: { name: 'chunk-commons', test: /[\\/]src[\\/]js[\\/]/, minChunks: 2, // minimum common number priority: 5, reuseExistingChunk: true } } }); 6.异步加载cdn

之前使用高德Amap获取行政区边界的时候,都是直接在public里面的index.html 直接引入,但是这样会很不好,登录页的时候就会加载AMap,有时甚至需要2-3s,所以这里我们把它抽出来动态创建 script 加载。  

这里我封装了下,直接使用即可。

const remoteLoad = url => { return new Promise((resolve, reject) => { const existingScript = document.getElementById(url); //如果script不存在 if (!existingScript) { const script = document.createElement('script'); script.id = url; script.src = url; script.async = true; document.body.appendChild(script); script.onload = function() { setTimeout(() => { this.onerror = this.onload = null; resolve(); }, 500); }; script.onerror = function() { this.onerror = this.onload = null; reject('加载失败' + url); }; } else { setTimeout(() => { resolve(); }, 500); } }) } export default remoteLoad;

使用方法:

async init() { try { await remoteLoad(TinymceCDN); if (window.tinymce) { this.initTinymce(); } else { this.$message.error('加载资源失败'); } } catch (error) { console.log(error); this.$message.error(error); } }, 7. 封装获取geoJson的方法

以前写的时候没有对geoJson进行封装,每个页面如果需要获取地图geoJson都必须得重新获取,页面看起来很多重复代码,所以这次递归生成geoJson。

使用递归的原因是由于高德不能获取到县的geoJson,所以只能从市的geoJson里面去把县的geoJson抠出来

//先异步加载cdn再 调用方法 export function getGeoJson(adcode, childAdcode = '') { return new Promise((resolve, reject) => { if (window.AMap && window.AMapUI) { insideFun(adcode, childAdcode); } else { remoteLoad(AMapCDN).then(() => { if (window.AMap) { remoteLoad(AMapUiCDN).then(() => { if (window.AMapUI) { insideFun(adcode, childAdcode); } else { console.error('AMapUI获取失败'); } }); } else { console.error('AMap获取失败'); } }); } function insideFun(adcode, childAdcode) { AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => { var districtExplorer = new DistrictExplorer(); districtExplorer.loadAreaNode(adcode, function(error, areaNode) { if (error) { console.error(error); reject(error); return; } let Json = areaNode.getSubFeatures(); if (Json.length === 0) { let parent = areaNode._data.geoData.parent.properties.acroutes; insideFun(parent[parent.length - 1], adcode); return; } if (childAdcode) { Json = Json.filter(item => { return item.properties.adcode == childAdcode; }); } let mapJson = { features: Json }; resolve(mapJson); }); }); } }); } 8.CDN抽离

由于打包后的文件很大,所以在生产环境使用CDN,开发环境使用本地依赖,不过这样会导致线上的bug很难排查,慎用。

vue.config.jsconst cdn = { css: [], js: [VueCDN, AxiosCDN, VueRouterCDN, VuexCDN], externals: { vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', axios: 'axios' }}; config.plugin('html').tap(args => { args[0].cdn = cdn; return args; }); index.html 最后

这样项目初始化基本上完成了,项目权限管理算是比较不错,其他基本功能也已经实现,还有些其他的功能感兴趣可以看看,本来之前还准备写几套自定义主题和国际化的,最后由于时间不够就放弃掉了。

项目地址:github.com/biubiubiu01…

其他文章

八.使用vue+antd搭建后台管理系统(实现篇)

七.使用vue+antd搭建后台管理系统(需求分析和搭建篇)

六.记一次Vue3.0尝鲜

五.记一次用webpack搭建vue项目

四.记一次用ts+vuecli4重构项目

二. Echarts+Amap实现点击下钻功能

一. vue keep-alive踩坑,删除keep-alive缓存



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3